#include "catalog.h"
#include "execution.h"
#include "plan.h"
#include "parser.h"
#include "semantic_analyzer.h"
#include "plan_generator.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "storage_system.h"

// 内存模拟页存储
static char* pages[100];

// 函数前向声明
char* trim_whitespace(char* str); 

void mock_storage_alloc_page(int page_id) {
    if (page_id < 0 || page_id >= 100) {
        return;
    }
    pages[page_id] = (char*)malloc(4096);
    memset(pages[page_id], 0, 4096);
}

// 释放内存页（模拟实现）
void mock_storage_free_page(int page_id) {
    if (page_id < 0 || page_id >= 100) {
        return;
    }
    if (pages[page_id]) {
        free(pages[page_id]);
        pages[page_id] = NULL;
    }
}

// 从文件读取SQL
char* read_sql_from_file(const char* filename) {
    FILE* file = fopen(filename, "r");
    if (!file) {
        fprintf(stderr, "Cannot open file: %s\n", filename);
        return NULL;
    }
    
    // 获取文件大小
    fseek(file, 0, SEEK_END);
    long size = ftell(file);
    fseek(file, 0, SEEK_SET);
    
    // 分配内存
    char* buffer = (char*)malloc(size + 1);
    if (!buffer) {
        fprintf(stderr, "Memory allocation failed\n");
        fclose(file);
        return NULL;
    }
    
    // 读取文件内容
    fread(buffer, 1, size, file);
    buffer[size] = '\0';
    
    fclose(file);
    return buffer;
}

// 处理单条SQL语句
int process_sql(const char* sql, Catalog* catalog) {
    printf("Processing SQL: %s\n\n", sql);
    
    // 创建词法分析器
    Lexer* lexer = create_lexer(sql);
    if (!lexer) {
        fprintf(stderr, "Failed to create lexer\n");
        return 1;
    }
    
    // 创建语法分析器
    Parser* parser = create_parser(lexer);
    if (!parser) {
        fprintf(stderr, "Failed to create parser\n");
        free_lexer(lexer);
        return 1;
    }
    
    // 解析SQL语句
    ASTNode* ast = parse_statement(parser);
    if (!ast) {
        fprintf(stderr, "Parsing failed\n");
        free_parser(parser);
        free_lexer(lexer);
        return 1;
    }
    
    // 执行语义分析
    SemanticResult semantic_result = analyze_semantics(ast, catalog);
    if (!semantic_result.success) {
        fprintf(stderr, "Semantic error at line %d, column %d: %s\n",
                semantic_result.error_line, semantic_result.error_column,
                semantic_result.error_message);
        free_semantic_result(semantic_result);
        free_ast_node(ast);
        free_parser(parser);
        free_lexer(lexer);
        return 1;
    }
    
    // 对于CREATE TABLE语句，添加到目录
    if (ast->type == NODE_CREATE_TABLE) {
        TableSchema* table_schema = create_table_schema_from_ast(ast);
        add_table_to_catalog(catalog, table_schema);
        printf("Table created successfully\n");
    }
    
    // 生成执行计划
    PlanNode* plan = generate_plan(ast, catalog);
    if (!plan) {
        fprintf(stderr, "Failed to generate execution plan\n");
        free_semantic_result(semantic_result);
        free_ast_node(ast);
        free_parser(parser);
        free_lexer(lexer);
        return 1;
    }
    
    // 打印执行计划
    printf("\nExecution Plan:\n");
    print_plan(plan, 0);
    
    // 执行计划
    int exec_result = execute_plan((const PlanNode*)plan, catalog);
    if (exec_result != 0) {
        fprintf(stderr, "Execution failed with code: %d\n", exec_result);
    } else {
        printf("SQL executed successfully\n");
    }
    
    // 释放资源
    free_plan(plan);
    free_semantic_result(semantic_result);
    free_ast_node(ast);
    free_parser(parser);
    free_lexer(lexer);
    
    return exec_result;
}

// 批量测试函数
void run_batch_tests(const char* filename, Catalog* catalog) {
    char* sql_content = read_sql_from_file(filename);
    if (!sql_content) {
        fprintf(stderr, "Failed to read test file: %s\n", filename);
        return;
    }
    
    // 创建临时词法分析器来跳过文件开头的注释和空白
    Lexer* temp_lexer = create_lexer(sql_content);
    if (!temp_lexer) {
        fprintf(stderr, "Failed to create lexer\n");
        free(sql_content);
        return;
    }
    
    // 跳过文件开头的空白字符和注释
    skip_whitespace(temp_lexer);
    
    // 记录第一个非空白、非注释的位置
    int content_start = temp_lexer->position;
    free_lexer(temp_lexer);
    
    // 从有效内容开始处理
    char* processed_content = sql_content + content_start;
    
    // 使用分号分割SQL语句，但正确处理字符串和注释中的分号
    char* stmt = strtok(processed_content, ";");
    int test_case = 1;
    
    while (stmt) {
        // 去除语句前后的空白字符
        char* trimmed_stmt = trim_whitespace(stmt);
        
        if (trimmed_stmt && strlen(trimmed_stmt) > 0) {
            printf("\n\n===== Test Case %d =====\n", test_case);
            
            // 在语句末尾添加分号，确保符合语法要求
            int stmt_len = strlen(trimmed_stmt);
            char* sql_with_semicolon = (char*)malloc(stmt_len + 2); // +1 for semicolon, +1 for null terminator
            if (sql_with_semicolon) {
                strcpy(sql_with_semicolon, trimmed_stmt);
                sql_with_semicolon[stmt_len] = ';';
                sql_with_semicolon[stmt_len + 1] = '\0';
                
                // 处理SQL语句
                process_sql(sql_with_semicolon, catalog);
                
                free(sql_with_semicolon);
            }
            
            free(trimmed_stmt);
            test_case++;
        }
        
        // 获取下一个语句
        stmt = strtok(NULL, ";");
    }
    
    free(sql_content);
}

// 辅助函数：去除字符串前后的空白字符
char* trim_whitespace(char* str) {
    if (!str) return NULL;
    
    // 去除前导空白
    while (isspace(*str)) str++;
    
    if (*str == '\0') {
        // 字符串全是空白字符
        char* empty_str = (char*)malloc(1);
        if (empty_str) *empty_str = '\0';
        return empty_str;
    }
    
    // 去除尾随空白
    char* end = str + strlen(str) - 1;
    while (end > str && isspace(*end)) end--;
    
    // 复制修剪后的字符串
    int len = end - str + 1;
    char* trimmed = (char*)malloc(len + 1);
    if (trimmed) {
        strncpy(trimmed, str, len);
        trimmed[len] = '\0';
    }
    
    return trimmed;
}

int main(int argc, char** argv) {
    // 初始化内存页
    for (int i = 0; i < 100; i++) {
        pages[i] = NULL;
    }

    // 新增：选择数据目录（默认 "data"）
    const char *data_dir = "data";

    // 新增：初始化存储子系统（必须在任何读/写页面之前调用）
    // init_storage_system 在 src/storage/storage_system.c 中实现，返回 STORAGE_OK 表示成功
    if (init_storage_system(data_dir) != STORAGE_OK) {
        fprintf(stderr, "Failed to init storage system with data dir '%s'\n", data_dir);
        return 1;
    }

    // 新增：确保系统表页可用（bootstrap 会创建 _tables/_columns 等页）
    if (catalog_bootstrap() != 0) {
        fprintf(stderr, "Failed to bootstrap catalog\n");
        shutdown_storage_system(); // 清理已初始化的存储子系统
        return 1;
    }

    // 创建目录（内存目录）
    Catalog* catalog = create_catalog();
    if (!catalog) {
        fprintf(stderr, "Failed to create catalog\n");
        shutdown_storage_system();
        return 1;
    }

    // 命令行参数处理
    if (argc > 2 && strcmp(argv[1], "--batch") == 0) {
        // 批量测试模式
        run_batch_tests(argv[2], catalog);
    } else if (argc > 1) {
        // 从文件读取SQL
        char* sql_input = read_sql_from_file(argv[1]);
        if (!sql_input) {
            free_catalog(catalog);
            shutdown_storage_system();
            return 1;
        }
        process_sql(sql_input, catalog);
        free(sql_input);
    } else {
        // 交互式命令行模式
        printf("SQL Database System\n");
        printf("Type SQL commands (end with ;), or 'exit' to quit\n\n");

        char buffer[4096];
        while (1) {
            printf("sql> ");

            // 读取用户输入
            size_t len = 0;
            char c;
            while ((c = getchar()) != EOF && c != '\n') {
                if (len >= sizeof(buffer) - 1) {
                    fprintf(stderr, "Input too long\n");
                    break;
                }
                buffer[len++] = c;
            }
            buffer[len] = '\0';

            // 检查退出命令
            if (strcmp(buffer, "exit") == 0) {
                break;
            }

            // 处理SQL语句
            if (len > 0) {
                process_sql(buffer, catalog);
            }
        }
    }

    // 释放目录
    free_catalog(catalog);

    // 释放内存页
    for (int i = 0; i < 100; i++) {
        if (pages[i]) {
            free(pages[i]);
        }
    }

    shutdown_storage_system();

    printf("Database closed\n");
    return 0;
}